package com.zbs.framework.common.handler;

import com.zbs.framework.common.config.IpInterceptorConfig;
import com.zbs.framework.common.constant.Constants;
import com.zbs.framework.common.service.IpAdderInterceptorService;
import com.zbs.framework.common.utils.IPAddressUtils;
import com.zbs.framework.common.utils.ResponseUtil;
import com.zbs.framework.common.utils.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器继承HandlerInterceptorAdapter 类
 */
@Slf4j
public class IpAdderInterceptor implements HandlerInterceptor {

    private final IpAdderInterceptorService ipAdderInterceptorService;

    public IpAdderInterceptor(IpAdderInterceptorService ipAdderInterceptorService) {
        this.ipAdderInterceptorService = ipAdderInterceptorService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String ip = IPAddressUtils.getIpAddr(request);
        if (ipAdderInterceptorService.isBlack(ip)) {
            ResponseUtil.out(response,request, ResultUtil.error("您已被列入黑名单！"));
            return false;
        }
        if (!Constants.ipMap.containsKey(ip)) {
           initIpVisitsNumber(ip);
            return true;
        }
        long currentTimeMillis = System.currentTimeMillis();
        Long time = Constants.limitedIpMap.get(ip);
        if (time != null) {
            if (time - currentTimeMillis > 0) {
                log.error("{} 访问过于频繁,所在地：{}",ip,IPAddressUtils.getAddress(ip));
                ResponseUtil.out(response,request, ResultUtil.error("访问过于频繁"));
                return false;
            }
            Constants.limitedIpMap.remove(ip);
        }
        Long[] ipArr = Constants.ipMap.get(ip);
        ipArr[0] += 1;
        if (ipArr[0] >=  IpInterceptorConfig.LIMIT_NUM) {
            long timeDifference =  currentTimeMillis - ipArr[1];
            if (timeDifference <= IpInterceptorConfig.MIN_SAFE_TIME) {
                Constants.limitedIpMap.put(ip, currentTimeMillis + IpInterceptorConfig.LIMIT_TIME);
                ResponseUtil.out(response,request, ResultUtil.error("访问过于频繁"));
                return false;
            } else {
                initIpVisitsNumber(ip);
            }
        }
        return true;
    }

    /**
     * 初始化用户访问次数和访问时间
     *
     * @param ip
     */
    private void initIpVisitsNumber(String ip) {
        Long[] ipInfo = new Long[2];
        ipInfo[0] = 0L;// 访问次数
        ipInfo[1] = System.currentTimeMillis();// 初次访问时间
        Constants.ipMap.put(ip, ipInfo);
    }
}

//需要将拦截器加载到WebMvcConfigurerAdapter
@Configuration
class IpWebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private IpAdderInterceptorService ipAdderInterceptorService;


    @Bean
    public IpAdderInterceptor ipAdderInterceptor() {
        return new IpAdderInterceptor(ipAdderInterceptorService);
    }



    public void addInterceptors(InterceptorRegistry registry) {
        if (IpInterceptorConfig.ENABLE) {
            registry.addInterceptor(ipAdderInterceptor());
        }
    }

}

